#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QDateTime>
#include <QRandomGenerator>
#include <QDebug>
#include <QBuffer>
#include <QNetworkRequest>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QCryptographicHash>
#include <QtGlobal>
#include <QUrlQuery>
#include <QMessageAuthenticationCode>
#include <QMediaDevices>  // 添加媒体设备支持


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 初始化网络管理器
    networkManager = new QNetworkAccessManager(this);

    connect(networkManager, &QNetworkAccessManager::finished,
            this, &MainWindow::handleApiReply);
    qDebug()<<"初始化网络管理器成功";
    // 设置窗口标题
    this->setWindowTitle("车辆信息识别系统");

    // 设置按钮样式
    ui->Btn_Picture->setStyleSheet("QPushButton { background-color: #4CAF50; color: white; font-weight: bold; border-radius: 5px; }"
                                   "QPushButton:hover { background-color: #45a049; }");

    ui->Btn_Car_Inf->setStyleSheet("QPushButton { background-color: #008CBA; color: white; font-weight: bold; border-radius: 5px; }"
                                   "QPushButton:hover { background-color: #007B9E; }");

    // 设置拍照按钮样式
    ui->Btn_Shooting->setStyleSheet("QPushButton { background-color: #f44336; color: white; font-weight: bold; border-radius: 5px; }"
                                    "QPushButton:hover { background-color: #d32f2f; }");

    // 检查并初始化相机
    if (QMediaDevices::videoInputs().isEmpty()) {
        QMessageBox::warning(this, "相机不可用", "未检测到可用摄像头");
        ui->Btn_Shooting->setEnabled(false);
    } else {
        // 创建视频显示部件
        videoWidget = new QVideoWidget(ui->label_picture);
        videoWidget->resize(ui->label_picture->size());
        videoWidget->hide();

        // 初始化相机系统
        camera = new QCamera(QMediaDevices::defaultVideoInput(), this); // 使用默认摄像头
        captureSession.setCamera(camera);
        imageCapture = new QImageCapture(this);
        captureSession.setImageCapture(imageCapture);
        captureSession.setVideoOutput(videoWidget);
        qDebug()<<"初始化初始化相机成功";

        // 连接信号
        connect(imageCapture, &QImageCapture::imageCaptured, this, &MainWindow::imageCaptured);
        connect(imageCapture, &QImageCapture::errorOccurred, this, [=](int id, QImageCapture::Error error, const QString &errorString) {
            Q_UNUSED(id);
            Q_UNUSED(error);
            QMessageBox::critical(this, "拍照错误", errorString);
        });
    }

    // 连接拍照按钮
    connect(ui->Btn_Shooting, &QPushButton::clicked, this, &MainWindow::on_Btn_Shooting_clicked);


    // ui->tableWidget->setColumnCount(7);
    // ui->tableWidget->setHorizontalHeaderLabels(
    //     QStringList() << "车牌号" << "品牌" << "车系" << "类型" << "颜色" << "进入时间" << "离开时间");
    // ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    // ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    // ui->tableWidget->show();

    ui->tableWidget->setColumnCount(7);
    ui->tableWidget->setHorizontalHeaderLabels(
        QStringList() << "车牌号" << "品牌" << "车系" << "类型" << "颜色" << "进入时间" << "离开时间");
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);

    // 获取水平表头
    QHeaderView *header = ui->tableWidget->horizontalHeader();

    // 先设置所有列自动拉伸（Stretch模式）
    header->setSectionResizeMode(QHeaderView::Stretch);

    header->setSectionResizeMode(0, QHeaderView::Fixed);
    ui->tableWidget->setColumnWidth(0, 80);

    // 单独设置颜色列（第5列）为固定宽度
    header->setSectionResizeMode(4, QHeaderView::Fixed);  // 索引从0开始，颜色是第5列
    ui->tableWidget->setColumnWidth(4, 40);  // 设置颜色列宽度为80像素

    // 单独设置时间列（第6-7列）为交互模式（可手动调整，也可代码设置宽度）
    //header->setSectionResizeMode(5, QHeaderView::Interactive);  // 进入时间（可手动）
    header->setSectionResizeMode(5, QHeaderView::Fixed);
    header->setSectionResizeMode(6, QHeaderView::Fixed);  // 离开时间
    ui->tableWidget->setColumnWidth(5, 140);  // 设置进入时间列宽度
    ui->tableWidget->setColumnWidth(6, 140);  // 设置离开时间列宽度

    ui->tableWidget->show();


    // 添加相机超时定时器
    cameraTimer = new QTimer(this);
    cameraTimer->setSingleShot(true);
    connect(cameraTimer, &QTimer::timeout, this, [this]() {
        if (capturing) {
            QMessageBox::warning(this, "相机超时", "拍照操作超时，请重试");
            capturing = false;
            ui->Btn_Shooting->setEnabled(true);
            if (camera->isActive()) {
                camera->stop();
                videoWidget->hide();
            }
        }
    });

    // 添加图像缩放异步处理器
    imageScalingWatcher = new QFutureWatcher<QPixmap>(this);
    connect(imageScalingWatcher, &QFutureWatcher<QPixmap>::finished, this, [this]() {
        QPixmap scaled = imageScalingWatcher->result();
        if (!scaled.isNull()) {
            ui->label_picture->setPixmap(scaled);
        }
        capturing = false;
        ui->Btn_Shooting->setEnabled(true);
    });

    // 初始化网络套接字
    tcpSocket = new QTcpSocket(this);
    connect(tcpSocket, &QTcpSocket::connected, this, [this]() {
        qDebug() << "已连接到服务器";
    });
    connect(tcpSocket, &QTcpSocket::errorOccurred, this, [this](QAbstractSocket::SocketError error) {
        qDebug() << "连接错误:" << tcpSocket->errorString();
    });

    // 尝试连接到服务器
    tcpSocket->connectToHost(serverIP, serverPort);

}

void MainWindow::saveCarInfo(const QString& plateNumber, const QString& brand,
                             const QString& series, const QString& type,
                             const QString& color, bool isEntering)
{
    // 如果是进入操作
    if (isEntering) {
        CarRecord record;
        record.plateNumber = plateNumber;
        record.brand = brand;
        record.series = series;
        record.type = type;
        record.color = color;
        record.enterTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        record.leaveTime = "尚未离开";
        record.isActive = true;
        carRecords.append(record);
    }
    // 如果是离开操作
    else {
        // 查找对应的进入记录
        for (int i = 0; i < carRecords.size(); i++) {
            if (carRecords[i].plateNumber == plateNumber && carRecords[i].isActive) {
                carRecords[i].leaveTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
                carRecords[i].isActive = false;
                break;
            }
        }
    }

    updateTable();

    // 发送数据到服务器
    if (tcpSocket && tcpSocket->state() == QAbstractSocket::ConnectedState) {
        QJsonObject json;
        if (isEntering) {
            json["type"] = "enter";
            json["plate"] = plateNumber;
            json["brand"] = brand;
            json["series"] = series;
            json["car_type"] = type;  // 修改键名避免冲突
            json["color"] = color;
            json["enter_time"] = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        } else {
            json["type"] = "exit";
            json["plate"] = plateNumber;
            // 添加离开时间
            json["leave_time"] = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        }

        QJsonDocument doc(json);
        tcpSocket->write(doc.toJson());
        tcpSocket->flush();  // 确保数据立即发送
        qDebug() << "已发送数据到服务器:" << doc.toJson();
    } else {
        qDebug() << "未连接到服务器，无法发送数据";
        if (tcpSocket) {
            qDebug() << "Socket状态:" << tcpSocket->state();
            qDebug() << "Socket错误:" << tcpSocket->errorString();
        }
    }
}

void MainWindow::updateTable()
{
    ui->tableWidget->setRowCount(carRecords.size());

    for (int i = 0; i < carRecords.size(); i++) {
        const CarRecord &record = carRecords[i];

        ui->tableWidget->setItem(i, 0, new QTableWidgetItem(record.plateNumber));
        ui->tableWidget->setItem(i, 1, new QTableWidgetItem(record.brand));
        ui->tableWidget->setItem(i, 2, new QTableWidgetItem(record.series));
        ui->tableWidget->setItem(i, 3, new QTableWidgetItem(record.type));
        ui->tableWidget->setItem(i, 4, new QTableWidgetItem(record.color));
        ui->tableWidget->setItem(i, 5, new QTableWidgetItem(record.enterTime));
        ui->tableWidget->setItem(i, 6, new QTableWidgetItem(record.leaveTime));

        // 设置行颜色：绿色表示车辆在场，灰色表示已离开
        QColor rowColor = record.isActive ? QColor(220, 255, 220) : QColor(240, 240, 240);
        for (int col = 0; col < 7; col++) {
            ui->tableWidget->item(i, col)->setBackground(rowColor);
        }
    }
}


MainWindow::~MainWindow()
{
    // 先停止异步操作
    if (imageScalingWatcher && imageScalingWatcher->isRunning()) {
        imageScalingWatcher->cancel();
        imageScalingWatcher->waitForFinished();
    }

    // 再停止相机
    if (camera && camera->isActive()) {
        camera->stop();
    }
    qDebug()<<"退出成功";
    delete ui;
}

void MainWindow::resizeEvent(QResizeEvent *event)
{
    QMainWindow::resizeEvent(event);
    if (videoWidget) {
        videoWidget->resize(ui->label_picture->size());
    }
}

void MainWindow::on_Btn_Shooting_clicked()
{
    if (!camera || capturing) return;

    capturing = true;
    ui->Btn_Shooting->setEnabled(false);
    cameraTimer->start(5000); // 5秒超时

    if (camera->isActive()) {
        imageCapture->capture();
    } else {
        camera->start();
        videoWidget->show();
        videoWidget->resize(ui->label_picture->size());
        ui->label_picture->clear();
        capturing = false; // 启动相机不算拍照操作
        ui->Btn_Shooting->setEnabled(true);
    }
}


void MainWindow::imageCaptured(int id, const QImage &preview)
{
    Q_UNUSED(id);

    // 不要立即停止相机，保持预览状态
    videoWidget->hide();

    // 异步处理图像缩放
    QSize targetSize = ui->label_picture->size();
    imageScalingWatcher->setFuture(QtConcurrent::run([preview, targetSize]() {
        return QPixmap::fromImage(preview.scaled(targetSize,
                                                 Qt::KeepAspectRatio,
                                                 Qt::SmoothTransformation));
    }));

    // 保存原始图像
    currentImage = QPixmap::fromImage(preview);
}

void MainWindow::on_Btn_Picture_clicked()
{
    // 打开文件对话框选择图片
    QString imagePath = QFileDialog::getOpenFileName(this,
                                                     tr("打开车辆图片"),
                                                     "",
                                                     tr("图片文件 (*.png *.jpg *.jpeg *.bmp)")
                                                     );

    if(imagePath.isEmpty()) return;

    // 加载图片并显示
    if(currentImage.load(imagePath)) {
        QPixmap scaledImage = currentImage.scaled(ui->label_picture->width(),
                                                  ui->label_picture->height(),
                                                  Qt::KeepAspectRatio,
                                                  Qt::SmoothTransformation);
        ui->label_picture->setPixmap(scaledImage);
        ui->label_picture->setAlignment(Qt::AlignCenter);
        qDebug()<<"加载图片并显示";
    } else {
        QMessageBox::warning(this, "错误", "无法加载图片！");
    }
}

QString MainWindow::generateTc3Signature(const QByteArray &payload, qint64 timestamp)
{
    QString date = QDateTime::fromSecsSinceEpoch(timestamp, Qt::UTC).toString("yyyy-MM-dd");

    // 1. 生成规范请求
    QString canonicalHeaders = QString("content-type:application/json; charset=utf-8\n"
                                       "host:%1\n").arg(endpoint);

    QString signedHeaders = "content-type;host";

    QString canonicalRequest = QString("POST\n"
                                       "/\n"          // 路径
                                       "\n"           // 空查询字符串
                                       "%1"           // headers
                                       "\n"           // 空行
                                       "%2\n"         // signed headers
                                       "%3")          // payload hash
                                   .arg(canonicalHeaders)
                                   .arg(signedHeaders)
                                   .arg(QString(QCryptographicHash::hash(payload, QCryptographicHash::Sha256).toHex()));

    // 2. 生成待签名字符串
    QString algorithm = "TC3-HMAC-SHA256";
    QString credentialScope = QString("%1/%2/tc3_request").arg(date).arg(service);
    QString hashedCanonicalRequest = QString(QCryptographicHash::hash(canonicalRequest.toUtf8(),
                                                                      QCryptographicHash::Sha256).toHex());

    QString stringToSign = QString("%1\n%2\n%3\n%4")
                               .arg(algorithm)
                               .arg(timestamp)
                               .arg(credentialScope)
                               .arg(hashedCanonicalRequest);

    // 3. 计算签名（修正密钥派生）
    QByteArray kDate = QMessageAuthenticationCode::hash(date.toUtf8(),
                                                        "TC3" + secretKey.toUtf8(),
                                                        QCryptographicHash::Sha256);
    QByteArray kService = QMessageAuthenticationCode::hash(service.toUtf8(),
                                                           kDate,
                                                           QCryptographicHash::Sha256);
    QByteArray signKey = QMessageAuthenticationCode::hash("tc3_request",
                                                          kService,
                                                          QCryptographicHash::Sha256);

    QByteArray signature = QMessageAuthenticationCode::hash(
                               stringToSign.toUtf8(),
                               signKey,
                               QCryptographicHash::Sha256
                               ).toHex();

    // 4. 构造授权头
    return QString("%1 Credential=%2/%3, SignedHeaders=%4, Signature=%5")
        .arg(algorithm)
        .arg(secretId)
        .arg(credentialScope)
        .arg(signedHeaders)
        .arg(QString(signature));
}


void MainWindow::on_Btn_Car_Inf_clicked()
{
    if(currentImage.isNull()) {
        QMessageBox::warning(this, "警告", "请先打开车辆图片！");
        return;
    }

    // 将图片转换为Base64
    QByteArray imageData;
    QBuffer buffer(&imageData);
    buffer.open(QIODevice::WriteOnly);
    currentImage.save(&buffer, "JPG");
    QString base64Image = imageData.toBase64();

    // 构造请求JSON
    QJsonObject requestJson;
    requestJson["ImageBase64"] = base64Image;
    QJsonDocument doc(requestJson);
    QByteArray payload = doc.toJson();

    // 生成统一时间戳
    qint64 timestamp = QDateTime::currentDateTimeUtc().toSecsSinceEpoch();

    // 生成签名
    QString authorization = generateTc3Signature(payload, timestamp);

    // 设置请求头（添加必需字段）
    QNetworkRequest request;
    request.setUrl(QUrl("https://" + endpoint));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=utf-8");
    request.setRawHeader("Authorization", authorization.toUtf8());
    request.setRawHeader("X-TC-Action", action.toUtf8());
    request.setRawHeader("X-TC-Version", version.toUtf8());
    request.setRawHeader("X-TC-Timestamp", QString::number(timestamp).toUtf8()); // 必需
    request.setRawHeader("X-TC-Region", region.toUtf8()); // 必需
    request.setRawHeader("Host", endpoint.toUtf8()); // 必需

    // 发送API请求
    networkManager->post(request, payload);
}

void MainWindow::handleApiReply(QNetworkReply *reply)
{
    if (reply->error() != QNetworkReply::NoError) {
        QMessageBox::critical(this, "API错误",
                              QString("请求失败: %1").arg(reply->errorString()));
        reply->deleteLater();
        return;
    }

    // 解析API响应
    QByteArray response = reply->readAll();
    QJsonDocument jsonDoc = QJsonDocument::fromJson(response);
    QJsonObject jsonObj = jsonDoc.object();

    // 调试输出
    qDebug() << "API Response:" << jsonDoc.toJson();

    if (jsonObj.contains("Response") && jsonObj["Response"].isObject()) {
        QJsonObject responseObj = jsonObj["Response"].toObject();

        if (responseObj.contains("Error")) {
            QJsonObject errorObj = responseObj["Error"].toObject();
            QString errorMsg = QString("错误代码: %1\n错误信息: %2")
                                   .arg(errorObj["Code"].toString())
                                   .arg(errorObj["Message"].toString());
            QMessageBox::warning(this, "API返回错误", errorMsg);
        } else if (responseObj.contains("CarTags")) {
            QJsonArray carTags = responseObj["CarTags"].toArray();

            if (!carTags.isEmpty()) {
                // 取第一辆车的识别结果
                QJsonObject carInfo = carTags[0].toObject();

                // 获取车辆基本信息
                QString carBrand = carInfo["Brand"].toString();
                QString carType = carInfo["Type"].toString();
                QString carColor = carInfo["Color"].toString();
                QString carSeries = carInfo["Serial"].toString();

                qDebug()<<""<<carInfo["Brand"].toString();
                qDebug()<<""<<carInfo["Type"].toString();
                qDebug()<<""<<carInfo["Color"].toString();
                qDebug()<<""<<carInfo["Serial"].toString();

                // 车牌信息
                QString plateNumber = "未识别到车牌";
                double plateConfidence = 0;

                if (carInfo.contains("PlateContent")) {
                    QJsonObject plateInfo = carInfo["PlateContent"].toObject();
                    plateNumber = plateInfo["Plate"].toString();
                    plateConfidence = plateInfo["Confidence"].toDouble();
                }

                // 显示识别结果
                ui->Text_Chepai->setText(plateNumber);
                qDebug()<<plateNumber;


                // 检查车辆是否已记录在场
                bool isAlreadyPresent = false;
                for (const CarRecord &record : carRecords) {
                    if (record.plateNumber == plateNumber && record.isActive) {
                        isAlreadyPresent = true;
                        break;
                    }
                }

                // 根据车辆状态保存信息
                if (isAlreadyPresent) {
                    // 车辆离开k
                    saveCarInfo(plateNumber, "", "", "", "", false);

                    // 更新信息显示
                    QString info = QString("车牌号: %1\n状态: 已离开\n离开时间: %2")
                                       .arg(plateNumber)
                                       .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
                    ui->Other_Inf->setText(info);
                } else {
                    // 车辆进入
                    saveCarInfo(plateNumber, carBrand, carSeries, carType, carColor, true);

                    // 更新信息显示
                    QString info = QString("品牌: %1\n车系: %2\n类型: %3\n颜色: %4\n进入时间: %5")
                                       .arg(carBrand)
                                       .arg(carSeries)
                                       .arg(carType)
                                       .arg(carColor)
                                       .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
                    ui->Other_Inf->setText(info);
                }

                return;
            }
        }
    }
    QMessageBox::information(this, "识别结果", "未识别到车辆信息");
    reply->deleteLater();
}



